home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
assemblr
/
library
/
edit
/
fremacsr
/
mintform.asm
< prev
next >
Wrap
Assembly Source File
|
1987-02-18
|
9KB
|
343 lines
;History:173,1
page ,132
.xlist
include mintdefs.asm
.list
data segment byte public
extrn formb: word
extrn forme: word
extrn fend: word
extrn actptr: word
comment /
formhash is the hashing table for form names. It is a list of
pointers to forms. Each form, in turn, has a pointer to the next form whose
name hashes to the same entry in formhash. To add a new form, we must add the
name to the proper place in the table. To delete a form, the form name must
be removed from formhash. After the remaining forms have been moved up in
memory, their links in formhash and each of the forms must be updated.
We use -1 for NIL because is above any legal address that a form may
take on. When we adjust the hash links, we won't adjust any NILs because they
seem to be a form which is above the one being moved. /
public syntax_table
syntax_table dw NIL
;don't put anything here.
formhashsize equ 256
public formhash ;formhash is public for debugging purposes only.
formhash dw formhashsize dup(NIL)
hash_value dw ?
data ends
code segment byte public
assume cs:code, ds: data, es: data
;define a form. Enter with:
; si => name
; cx = name length
; di => data
; dx = data length
; bx = form pointer.
;this is what is accomplished: (a=active string, n=new form, o=old forms)
; aaaa nnnnnnnn ooooooo oooooooo
; ^ ^ ^
;actptr formb forme
; ^<------>^
; di cx si
public define_form
define_form:
push bx ;save the form pointer.
call find_form ;see if it already exists.
jnc define_form_1 ;it doesn't.
;check to see if the form is already big enough.
cmp dx,[bx].data_length
ja define_form_3 ;it isn't.
pop [bx].form_pointer ;set the form pointer.
mov si,di ;prepare to move the data.
lea di,[bx].name_offset ;->name.
add di,cx ;->data.
mov [bx].data_length,dx ;set the data length.
jmp short define_form_4
define_form_3:
push di
push si
push cx
call delete_form
pop cx
pop si
pop di
define_form_1:
pop bx ;restore form pointer.
push di
push si
push cx
add cx,(size form) ;compute amount of space needed.
add cx,dx
push cx ;push the size
mov si,actptr
mov di,si
sub di,cx
mov ax,di ;see if we have that much space.
sub ax,free_space
cmp ax,fend
jb define_form_2 ;no, go show no mem
mov cx,formb ;compute the number of bytes to move.
sub cx,actptr
mov actptr,di ;update actptr
rep movsb
;di points to the free space. Leave it alone.
mov formb,di
pop [di].form_length ;get the total size. (pushed as cx)
mov [di].form_pointer,bx
pop cx ;we have to pop into cx, because we
mov [di].name_length,cx ; need it later for the movsb.
mov [di].data_length,dx
pop si ;restore ->name
call hash_func
mov ax,[bx] ;get current formhash
mov [bx],di ;make formhash point to us.
mov [di].hash_link,ax ;make us point to current formhash.
add di,name_offset ;lea di,[di].name_offset
rep movsb
pop si ;restore ->data
define_form_4:
;here with dx=data size, si->data, di->data area in form.
mov cx,dx
rep movsb
ret
define_form_2:
jmp nomem
;Find a form. Enter with:
; si => name
; cx = name length
;Preserve di
;Exit with:
; bx => form
; cy if form found,
; nc if form not found.
public find_form
find_form:
push dx
push di
call hash_func
mov hash_value,bx ;remember the formhash pointer.
xor dx,dx
mov bx,[bx] ;get ->first form that hashes here.
find_form_1:
cmp bx,NIL ;end of list?
je find_form_2 ;yes, we didn't find it.
cmp cx,[bx].name_length ;lengths equal?
jne find_form_3 ;no, go to next.
lea di,[bx].name_offset ;compare names.
push si
push cx
rep cmpsb
pop cx
pop si
jne find_form_3 ;names not equal.
or dx,dx ;did we find it first?
je find_form_4 ;yes - that's where we want it.
mov di,hash_value ;get the head of the list.
mov ax,[di]
mov [di],bx ;make head -> found.
xchg ax,[bx].hash_link ;make found -> old head.
mov di,dx
mov [di].hash_link,ax ;make pred(found) -> succ(found).
find_form_4:
stc ;found the form!
pop di
pop dx
ret
find_form_3:
mov dx,bx
mov bx,[bx].hash_link
jmp find_form_1
find_form_2:
clc ;didn't find the form!
pop di
pop dx
ret
;delete a form. Enter with:
; bx=>form
;this is what is accomplished: (a=active string, f=forms, d=deleted form)
; aaaa ffffffff ddddddddddd ffffffff
; ^ ^ ^ ^^^^^^^ ^
;actptr formb bx delete forme
; <-------------->^ ^
; cx si di
public delete_form
delete_form:
;delete the form from the hashing table.
mov di,bx ;make a copy of the pointer to the form.
mov cx,[bx].name_length
lea si,[bx].name_offset
call hash_func
sub bx,hash_link ;pretend that formhash is a form itself.
delete_form_1:
cmp [bx].hash_link,di ;does this form point to us?
je delete_form_2 ;yes.
mov bx,[bx].hash_link ;no - go to the next form.
jmp delete_form_1
delete_form_2:
mov ax,[di].hash_link ;unlink us from the list.
mov [bx].hash_link,ax
;check for deletion of the syntax table.
cmp di,syntax_table
jne delete_form_7
mov syntax_table,NIL ;if we're deleting it, put NIL in.
delete_form_7:
;now adjust the hash links in formhash.
mov ax,[di].form_length
mov bx,offset syntax_table
mov cx,formhashsize+1 ;add one for the syntax table.
delete_form_3:
cmp [bx],di ;do we need to adjust this one?
jae delete_form_4 ;no.
add [bx],ax ;yes - do it.
delete_form_4:
add bx,2
loop delete_form_3
;now adjust all the hash links in the forms. Notice that we are adjusting
; the hash link in the form we are about to delete, but it doesn't hurt.
; We can also presume the existence of at least one form at this point.
mov bx,formb
delete_form_5:
cmp [bx].hash_link,di ;do we need to adjust this one?
jae delete_form_6 ;no.
add [bx].hash_link,ax ;yes - do it.
delete_form_6:
add bx,[bx].form_length ;compute the form after this one.
cmp bx,forme ;no forms after this one.
jb delete_form_5
add formb,ax
mov si,di ;now move everything up.
add di,ax
mov cx,si
sub cx,actptr
dec si
dec di
std ;reverse move
rep movsb
cld
inc di ;update actptr
mov actptr,di
ret
;find the form whose name is given in arg1. Return the form pointer in
;si, and the number of bytes remaining in the form in cx.
public find_arg1
find_arg1:
mov cx,1
;fall through to find_arg
;find the form whose name is given in the argument specified in cx. Return
; the form pointer in si, and the number of bytes remaining in the form in cx,
; and the pointer to the form in bx.
public find_arg
find_arg:
call getarg
call find_form
jnc find_arg1_1 ;if form doesn't exist, exit.
mov si,bx ;make si => form.data
add si,name_offset
add si,[bx].name_length
add si,[bx].form_pointer
mov cx,[bx].data_length ;make cx = number of bytes left.
sub cx,[bx].form_pointer
stc ;remember that form was found.
find_arg1_1:
ret
;rehash is used when the hash structure is garbage, i.e., when a file has
; been bulk-loaded.
public rehash
rehash:
mov di,offset formhash ;kill all of the current pointers.
mov cx,formhashsize
mov ax,NIL
rep stosw
mov di,formb
rehash_1:
lea si,[di].name_offset ;->name.
mov cx,[di].name_length
call hash_func
mov ax,[bx] ;get current formhash
mov [bx],di ;make formhash point to us.
mov [di].hash_link,ax ;make us point to current formhash.
add di,[di].form_length
cmp di,forme
jb rehash_1
ret
hash_func:
;enter with si,cx ->name to be hashed.
;the particular function we will use is:
; value=(((char*2+char)*2+char)*2+char)*2+char ...
;of course, most of the chars will be in the range [A-Za-z], so this
; may not be the best hashing function. Time will tell.
;exit with entry into hash table in bx.
;preserve dl.
push si
push cx
xor bl,bl ;start with zero.
jcxz hash_func_1
hash_func_2:
add bl,bl ;*2
adc bl,0
lodsb
sub al,'a' ;subtract off the most probable char.
add bl,al ;+char
adc bl,0
loop hash_func_2
hash_func_1:
mov bh,0
add bx,bx
lea bx,formhash[bx] ;don't add bx,offset formhash!
pop cx
pop si
ret
;Adjust the form pointer after building a value which affects the
; form pointer. The new form pointer is derived from the count
; of characters left in cx. The form is pointed to by bx.
public set_form_pointer
set_form_pointer:
mov ax,[bx].data_length
sub ax,cx
mov [bx].form_pointer,ax
ret
public return_form
return_form:
call set_form_pointer
jmp return_tos
extrn return_tos: near
extrn getarg: near
extrn nomem: near
code ends
end